package com.hd.manager.controller;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.hd.appcommon.entity.*;
import com.hd.appcommon.mapper.DoorMapper;
import com.hd.appcommon.mapper.UserMapper;
import com.hd.appcommon.service.DoorService;
import com.hd.appcommon.service.RoomService;
import com.hd.appcommon.service.UserService;
import com.hd.hdxgddcommon.controller.AbstractController;
import com.hd.hdxgddcommon.entity.dto.ResultDto;
import com.hd.hdxgddcommon.page.MyPage;
import com.hd.hdxgddcommon.utils.StringUtils;
import com.hd.manager.util.*;
import com.hd.manager.webSocket.EndpointManager;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.lang.reflect.Field;
import java.util.*;
import java.util.stream.Collectors;

import static com.hd.manager.util.RequestIdUtil.getRequestId;

/**
 * @projectName:    entrance_guard
 * @package:        com.hd.manager.controller
 * @className:      RoomController
 * @author:     otto
 * @description:
 * @date:    2023/7/24 10:24
 * @version:    1.0
 */

@RestController
@RequestMapping("Room")
@Slf4j
public class RoomController extends AbstractController {
    @Autowired
    private UserMapper UserMapper;
    @Autowired
    private RoomService roomService;
    @Autowired
    private DoorService doorService;
    @Autowired
    private DoorMapper doorMapper;
    @Autowired
    private UserService userService;
    @Autowired
    private ImageUtil imageUtil;
    @Autowired
    private ZhengYuanUtil zhengYuanUtil;
//    @Autowired
//    private JieShiActivateRequestUtil jieShiActivateRequestUtil;
    @Autowired
    private JieShiActivateRequestCallBackUtil jieShiActivateRequestCallBackUtil;
    @RequestMapping("likeStudents")
    public ResultDto getStudentLikeMessage(HttpServletRequest request){
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.likeRight(User::getName,request.getParameter("input_name")).last(" limit 5 ");
        List<User> likeUsers = UserMapper.selectList(queryWrapper);
        System.out.println(likeUsers.toString());
        return success(likeUsers);
    }
    @RequestMapping("getRoom")
    public ResultDto getRoomMessage(MyPage page, String roomName,String buildingName){
        try{
            QueryWrapper<Room> queryWrapper = new QueryWrapper<>();
            if(StringUtils.isNotBlank(roomName)){
                queryWrapper.like("room_name","%"+roomName+"%");
            }
            if(StringUtils.isNotBlank(buildingName)){
                queryWrapper.like("building_name","%"+buildingName+"%");
            }
            return success(roomService.page(page,queryWrapper));
        }catch (Exception e){
            log.error(e.toString());
            return fail();
        }
    }
    @RequestMapping("getDoor")
    public ResultDto getDoor(MyPage page,String doorIdList){
        try{
            String[] doorIds = doorIdList.split(",");
            IPage<Door> doorIPage = doorService.page(page, new QueryWrapper<Door>().in("door_id",doorIds));
            return success(doorIPage);
        }catch (Exception e){
            log.error(e.toString());
            return fail();
        }
    }
    @RequestMapping("getUser")
    public ResultDto getUser(MyPage page,String roomId){
        try {
            Room room = roomService.getById(roomId);
            String userIdList = room.getUserIdList();
            String[] userIds = userIdList.split(",");
            IPage<User> userIPage = userService.page(page, new QueryWrapper<User>().in("job_number",userIds));
            return success(userIPage);
        }catch (Exception e){
            log.error(e.toString());
            return fail();
        }
    }

    /**
     * 添加用户信息
     * @param roomId 房间表id
     * @param sno 学生学号
     * @param image 图片数据base64格式
     * @return
     * @throws InterruptedException
     */
    @RequestMapping("addUserMessage")
    public ResultDto addUserMessage(String roomId, String sno, String image) throws InterruptedException {
        Room room = roomService.getById(roomId);
        String doorIdsList = room.getDoorIdList();
        String[] doorIdList = doorIdsList.split(",");
        List<Door> doorList = doorService.list(new QueryWrapper<Door>().in("door_id",doorIdList));
        // 对每一个门设备加入新信息
        User user;
        if(StringUtils.isNotBlank(sno)){
            user = userService.getOne(new QueryWrapper<User>().eq("job_number",sno).last("LIMIT 1"));
            if(user==null){
                return fail("用户不存在");
            }
        }
        else return fail("未指定用户！");
        String name = user.getName();
        String phoneNumber = user.getPhone();
        String cardId = user.getCardId();
        if(StringUtils.isBlank(cardId)){
            return fail("用户身份证信息不存在！");
        }
        List<JSONObject> resList = AddDoorUserMessage(doorList,name,phoneNumber,image,sno,cardId);
        Boolean suc = true;
        StringBuffer errorMsg = new StringBuffer();
        for (JSONObject jsonObject:
             resList) {
            String code = jsonObject.getString("code");
            String lockSucCode = jsonObject.getString("lockSucCode");
            System.out.println("lockSucCode: "+lockSucCode);
            if(StringUtils.isBlank(code)||(!code.equals("0")&&!code.equals("202"))||StringUtils.isBlank(lockSucCode)||!lockSucCode.equals("true")){
                suc = false;
                errorMsg.append("设备:"+jsonObject.getString("deviceID")+"\t错误码:"+jsonObject.getString("code")+"\n"+"lockSucCode: "+lockSucCode+"\n");
            }
        }
        // 如果全部成功就返回success()
        if(suc){
            // 更新本地信息
            String userIdList = room.getUserIdList();
            if(userIdList ==null){
                userIdList = "";
            }
            // 设备中用户存在而且本地数据库也存在，不需要更新房间中的用户id列表
            String[] userIdArray = userIdList.split(",");
            Boolean exist = false;
            for (String s:
                    userIdArray) {
                if(s.equals(sno)){
                    exist = true;
                }
            }
            if(!exist){
                // 设备中用户存在但本地数据库不存在，需要更新房间中的用户id列表
                String newUserIdList;
                if(userIdList.equals("")){
                    newUserIdList = sno;
                }
                else
                    newUserIdList = userIdList.concat(","+sno);
                roomService.update(new UpdateWrapper<Room>().eq("id",roomId).set("user_id_list",newUserIdList));
            }
            else{
                // 防止本地用户数据已有但用户图片或路径不存在
                String globalPath = imageUtil.savePicture(sno,image);
                // 更新用户的图片保存路径
                userService.update(new UpdateWrapper<User>().eq("job_number",sno).set("image_url",globalPath));
                return success("用户重复添加");
            }

            // 防止设备和本地用户存在了但是照片信息和照片路径不存在
            // 改用util统一管理图片储存、删除以及用户图片、开门记录图片保存路径
            // 调用用户图片储存方法 传入用户学号、工号 作为标识
            String globalPath = imageUtil.savePicture(sno,image);
            // 更新用户的图片保存路径
            userService.update(new UpdateWrapper<User>().eq("job_number",sno).set("image_url",globalPath));
            log.info("成功添加用户");
            return success();
        }
        // 否则返回fail同时携带一张map，填入请求失败的设备id和错误码
        else {
            // 因为不更新本地数据了，对之前操作的反向操作
            if(StringUtils.isBlank(user.getCardId()))
                return fail("用户身份证信息不存在！");
            deleteDoorUserMessage(doorList,user.getJobNumber(),user.getCardId());
            log.info("添加用户失败");
            return fail(errorMsg.toString());
        }
    }

    /**
     * 传入房间表主键和用户表主键 返回删除消息
     * @param roomId
     * @param jobNumber
     * @return
     */
    @RequestMapping("/deleteUserMessage")
    public ResultDto deleteUserMessage(String roomId, String jobNumber) throws InterruptedException {
//        try {
            Room room = roomService.getById(roomId);
            Long requestId = getRequestId();
            if(room==null)
                return success("找不到房间");
            String doorIdList = room.getDoorIdList();
            if(StringUtils.isBlank(doorIdList)){
                return success("该房间没有用户");
            }
            List<Door> doorList = doorService.list(new QueryWrapper<Door>().
                    in("door_id",doorIdList));
            List<JSONObject> resList = new ArrayList<>();
            User user = userService.getOne(new QueryWrapper<User>()
                    .eq("job_number",jobNumber)
                    .last("LIMIT 1"));
            if(user==null){
                return fail("用户不存在!");
            }
            if(StringUtils.isBlank(user.getCardId()))
                return fail("用户身份证信息不存在！");
            resList = deleteDoorUserMessage(doorList,jobNumber,user.getCardId());
            Boolean success = true;
            for (JSONObject jsonObject:
                    resList) {
                String code = jsonObject.getString("code");
                String lockSucCode = jsonObject.getString("lockSucCode");
                log.info("code: "+code);
                log.info("lockSucCode: "+lockSucCode);
                if(StringUtils.isBlank(code)||(!code.equals("0")&&!code.equals("-119"))||StringUtils.isBlank(lockSucCode)||!lockSucCode.equals("true")){
                    success = false;
                }
            }
            if(success){
                String userIdList = room.getUserIdList();
                List<String> userIdsList = Arrays.asList(userIdList.split(","));
                userIdsList = userIdsList.stream().filter(r-> !r.equals(jobNumber)).collect(Collectors.toList());
                String newUserIdList = String.join(",",userIdsList);
                System.out.println("newUserIdList "+newUserIdList);
                roomService.update(new UpdateWrapper<Room>().eq("id",roomId).set("user_id_list",newUserIdList));
                log.info("人员信息删除成功！");
                return success();
            }
            else{
                String image = imageUtil.fileToBase64(user.getImageUrl());
                String cardId = user.getCardId();
                if(StringUtils.isBlank(cardId)){
                    return fail("用户缺少身份证信息！");
                }
                AddDoorUserMessage(doorList,user.getName(),user.getPhone(),image,user.getJobNumber(),cardId);
                log.info("人员信息删除失败！");
                return fail("用户信息删除失败！");
            }
//        }catch (Exception e){
//            log.error(e.toString());
//            log.info("人员信息删除异常！");
//            return fail("删除用户信息异常");
//        }

    }


    private List<JSONObject> AddDoorUserMessage(List<Door> doorList,String name,String phoneNumber,String image,String sno,String cardId) throws InterruptedException {
        List<JSONObject> resList = new ArrayList<>();
        for (Door door:
                doorList) {
            String deviceId = door.getDeviceId();
            String pass = door.getPass();
            Long requestId = getRequestId();
            HashMap<String,String> userInfo = new HashMap();
            userInfo.put("name",name);
            userInfo.put("phone_number",phoneNumber);
            HashMap<String,Object> requestMap = new HashMap<>();
            requestMap.put("user_info",userInfo);
            requestMap.put("request_type","addUser");
            requestMap.put("device_id",deviceId);
            requestMap.put("request_id",requestId);
            requestMap.put("image_type","image");
            requestMap.put("image_content",image.trim());
            requestMap.put("user_id",sno);
            requestMap.put("pass",pass);
            JSONObject res = jieShiActivateRequestCallBackUtil.activateRequest(requestMap);
            Boolean lockAddRight = zhengYuanUtil.openCardRightAdd(door.getDoorLockCode(), Long.valueOf(cardId));
            res.put("lockSucCode",lockAddRight);
            resList.add(res);
        }
        return resList;
    }


    private List<JSONObject> deleteDoorUserMessage(List<Door> doorList,String jobNumber, String cardId) throws InterruptedException {
        List<JSONObject> resList = new ArrayList<>();
        for (Door door:
                doorList) {
            String deviceId = door.getDeviceId();
            String pass = door.getPass();
            String requestId = String.valueOf(getRequestId());
            HashMap<String,Object> requestMap = new HashMap<>();
            requestMap.put("request_type","deleteUser");
            requestMap.put("request_id",requestId);
            requestMap.put("user_id",jobNumber);
            requestMap.put("device_id",deviceId);
            requestMap.put("pass",pass);
            // 删除人脸识别设备的用户信息
            JSONObject res = jieShiActivateRequestCallBackUtil.activateRequest(requestMap);
            Boolean lockSucCode = zhengYuanUtil.openCardRightDelete(door.getDoorLockCode(), Long.valueOf(cardId));
            res.put("lockSucCode",lockSucCode);
            resList.add(res);
        }
        return resList;
    }

    /**
     * 拉取数据接口
     * @return
     * @throws InterruptedException
     */
    @RequestMapping("updateUserMessage")
    public ResultDto getUserMessage() throws InterruptedException {
//        try {
            List<Room> roomList = roomService.list(new QueryWrapper<>());
            List<JSONObject> resList = new ArrayList<>();
            for (Room room:
                 roomList) {
                String id = String.valueOf(room.getId());
                Long requestId = getRequestId();
                String doorIdList = room.getDoorIdList();
                String[] doorIds = doorIdList.split(",");
                if(doorIds!=null&&doorIds.length>0){
                    String doorId = doorIds[0];
                    Door door = doorService.getOne(new QueryWrapper<Door>().eq("door_id",doorId).last("LIMIT 1"));
                    String deviceId = door.getDeviceId();
                    String pass = door.getPass();
                    HashMap<String,Object> requestMap = new HashMap<>();
                    requestMap.put("device_id",deviceId);
                    requestMap.put("request_type","getUserList");
                    requestMap.put("request_id",requestId);
                    requestMap.put("pass",pass);
                    JSONObject res = jieShiActivateRequestCallBackUtil.activateRequest(requestMap);
                    JSONArray jsonArray = res.getJSONArray("user_id_list");
                    String newUserIdList = null;
                    if(jsonArray!=null&&jsonArray.size()!=0){
                        List<String> userIdList = JSONArray.parseArray(jsonArray.toJSONString(),String.class);
                        userIdList = userIdList.stream().map(r->{
                            r = r.substring(r.indexOf(":")+1);
                            return r.substring(r.indexOf("\"")+1,r.length()-2);
                        }).collect(Collectors.toList());
                        newUserIdList = String.join(",",userIdList);
                    }
                    roomService.update(new UpdateWrapper<Room>().eq("id",id).set("user_id_list",newUserIdList));
                    resList.add(res);
                }

            }
            if(resList.size()==0){
                success("无数据");
            }
            return success(resList);

//        }catch (Exception e){
//            log.error(e.toString());
//            return fail("fail");
//        }

    }

    @RequestMapping("getImageOutPutStream")
    public void getImageOutPutStream(HttpServletRequest request,HttpServletResponse response) throws IOException {
        System.out.println(request.getParameter("userId"));
        // 这里的userId相当于jobNumber
        String id = request.getParameter("id");
        User user = userService.getById(id);
        String filePath = user.getImageUrl();
        ServletOutputStream out =null;
        ByteArrayOutputStream baos = null;
        try {
            FileInputStream inStream = new FileInputStream(filePath);
            byte[] buffer = new byte[1024];
            int len;
            baos = new ByteArrayOutputStream();
            while ((len=inStream.read(buffer))!=-1){
                baos.write(buffer,0,len);
            }
            response.addHeader("Content-Disposition", "attachment;filename=" + id+".jpg");
            response.addHeader("Content-Length", "" + baos.size());
            response.setHeader("filename", id+".jpg");
            response.setContentType("application/blob");
            out = response.getOutputStream();
            out.write(baos.toByteArray());

        }catch (Exception e){
            e.printStackTrace();
            throw new RuntimeException();
        }finally {
            baos.flush();
            baos.close();
            out.flush();
            out.close();

        }
    }

    @RequestMapping("getImage")
    public String getImage(HttpServletRequest request){
        try {
            //filePath:图片完整路径
            // 使用id查询更快
            String id = request.getParameter("id");
            User user = userService.getById(id);
            String filePath = user.getImageUrl();
            System.out.println("返回图片路径： "+filePath);
            String newFilePath = filePath.substring(0,filePath.indexOf(".")).concat("Compression.jpg");
            File fileImage = new File(newFilePath);
            if(!fileImage.exists())
                imageUtil.ImageCompression(filePath,newFilePath,100,100, 0.5F);
            String base64 = imageUtil.fileToBase64(newFilePath);
            return base64;
        }catch (Exception e){
            e.printStackTrace();
            return null;
        }
    }



    @RequestMapping("getDoorDevice")
    public ResultDto getDoorDeviceMessage(String roomId){
        List<DoorVo> doorList = roomService.getDoorList(roomId);
        doorList  = doorList.stream().map(r->{
            r.setStatus(EndpointManager.enpointExist(r.getDeviceId()));
            return r;
        }).collect(Collectors.toList());
        return success(doorList);
    }

    @RequestMapping("deleteDoor")
    public ResultDto deleteDoorDeviceMessage(String doorId){
        String doorIdList = roomService.getDoorIdListByDoorId(doorId);
        List<String> doorIdsList = Arrays.asList(doorIdList.split(","));
        List<String> newDoorIdsList = doorIdsList.stream().filter(r-> !r.equals(doorId)).collect(Collectors.toList());
        String newDoorIdList = String.join(",",newDoorIdsList);
        roomService.updateUserIdListByDoorId(doorId,newDoorIdList);
        Boolean remove = doorService.remove(new QueryWrapper<Door>().eq("door_id",doorId));
        if(remove) return success();
        else return fail();
    }

    @RequestMapping("addOrUpdateDoor")
    /**
     * 在指定房间添加门设备
     */
    public ResultDto addOrUpdateDoorDeviceMessage(Door door){
        System.out.println(door);

        Integer doorId = doorService.exist(new QueryWrapper<Door>().
                eq("room_id",door.getRoomId()).
                and(i -> i.eq("device_id",door.getDeviceId()).
                        or().eq("door_lock_code",door.getDoorLockCode())));
        if(null!=doorId){
            System.out.println("更新");
            doorService.update(door, new QueryWrapper<Door>().eq("door_id",doorId));
        }
        else{
            System.out.println("新增");
            doorService.getBaseMapper().insert(door);
            doorId = door.getDoorId();
            System.out.println("doorId "+doorId);
            roomService.addDoorId(door.getRoomId(),doorId);
        }
        return success();
    }

    /**
     * 上传门设备信息 excel
     * @return 上传成功信息或上传失败的的行标
     */
    @RequestMapping("/import")
    public ResultDto ExcelImport(@RequestPart("file") MultipartFile file) throws Exception{
        List<RoomMessageUpload> roomMessageUploadList = ExcelUtils.readMultipartFile(file, RoomMessageUpload.class);
        Boolean success = true;
        int i = 1;
        StringBuffer errorMsg = new StringBuffer();
        for (RoomMessageUpload e:
                roomMessageUploadList) {
            if(!checkObjAllFieldsIsNotNull(e)){
                success = false;
                errorMsg.append("第"+i+"行信息不全\n");
                continue;
            }
            Boolean current = roomService.upLoadUserMessage(e);
            if(current==null||!current){
                success = false;
                errorMsg.append("第"+i+"行信息导入失败!\n");
            }
            i++;
        }
        if(success!=null&&success){
            return success("上传成功！");
        }
        else
        {
            return fail(errorMsg.toString());
        }
    }
    /**
     * 判断对象中属性值是否全为空
     *
     * @param object
     * @return
     */
    private boolean checkObjAllFieldsIsNotNull(Object object) {
        if (null == object) {
            return false;
        }

        try {
            for (Field f : object.getClass().getDeclaredFields()) {
                f.setAccessible(true);

                System.out.print(f.getName() + ":");
                System.out.println(f.get(object));

                if (f.get(object) == null || StringUtils.isBlank(f.get(object).toString())) {
                    return false;
                }

            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return true;
    }


}
